package com.boulderai.mcp.controller;

import com.boulderai.mcp.llm.LlmClientFactory;
import com.boulderai.mcp.model.llm.LlmMessage;
import com.boulderai.mcp.model.llm.LlmResponse;
import com.boulderai.mcp.service.LlmMcpService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;

import java.util.List;
import java.util.Map;

/**
 * 大模型API控制器
 * 提供与大模型交互的HTTP接口
 */
@RestController
@RequestMapping("/api/llm")
@CrossOrigin(origins = "*", maxAge = 3600)
public class LlmController {
    
    private static final Logger logger = LoggerFactory.getLogger(LlmController.class);
    
    @Autowired
    private LlmMcpService llmMcpService;
    
    @Autowired
    private LlmClientFactory llmClientFactory;
    
    /**
     * 与大模型对话（支持MCP工具调用）
     */
    @PostMapping("/chat/{sessionId}")
    public Mono<ResponseEntity<LlmResponse>> chat(
            @PathVariable String sessionId,
            @RequestBody ChatRequest request) {
        
        logger.info("Received chat request: sessionId={}, clientType={}, model={}, messages={}", 
                sessionId, request.getClientType(), request.getModel(), request.getMessages().size());
        
        return llmMcpService.chatWithMcp(
                sessionId, 
                request.getClientType(), 
                request.getModel(), 
                request.getMessages(),
                request.getClientConfig()
        )
        .map(ResponseEntity::ok)
        .onErrorReturn(ResponseEntity.badRequest().build());
    }
    
    /**
     * 流式对话接口
     */
    @PostMapping(value = "/chat/{sessionId}/stream", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
    public Flux<LlmResponse> chatStream(
            @PathVariable String sessionId,
            @RequestBody ChatRequest request) {
        
        logger.info("Received streaming chat request: sessionId={}, clientType={}, model={}, messages={}", 
                sessionId, request.getClientType(), request.getModel(), request.getMessages().size());
        
        return llmMcpService.chatStreamWithMcp(
                sessionId, 
                request.getClientType(), 
                request.getModel(), 
                request.getMessages(),
                request.getClientConfig()
        )
        .onErrorResume(error -> {
            logger.error("Error in streaming chat", error);
            return Flux.empty();
        });
    }
    
    /**
     * 获取支持的大模型客户端类型
     */
    @GetMapping("/clients")
    public ResponseEntity<ClientTypesResponse> getSupportedClientTypes() {
        String[] clientTypes = llmClientFactory.getSupportedClientTypes();
        return ResponseEntity.ok(new ClientTypesResponse(clientTypes));
    }
    
    /**
     * 获取指定客户端支持的模型列表
     */
    @GetMapping("/clients/{clientType}/models")
    public Mono<ResponseEntity<ModelsResponse>> getSupportedModels(
            @PathVariable String clientType,
            @RequestParam(required = false) Map<String, String> config) {
        
        try {
            if (!llmClientFactory.isClientTypeSupported(clientType)) {
                return Mono.just(ResponseEntity.badRequest().build());
            }
            
            return llmClientFactory.createClient(clientType, config)
                    .getSupportedModels()
                    .map(models -> ResponseEntity.ok(new ModelsResponse(models)))
                    .onErrorReturn(ResponseEntity.badRequest().build());
                    
        } catch (Exception e) {
            logger.error("Error getting supported models for client type: {}", clientType, e);
            return Mono.just(ResponseEntity.badRequest().build());
        }
    }
    
    /**
     * 检查指定客户端是否可用
     */
    @GetMapping("/clients/{clientType}/health")
    public ResponseEntity<HealthResponse> checkClientHealth(
            @PathVariable String clientType,
            @RequestParam(required = false) Map<String, String> config) {
        
        try {
            if (!llmClientFactory.isClientTypeSupported(clientType)) {
                return ResponseEntity.badRequest().build();
            }
            
            boolean available = llmClientFactory.createClient(clientType, config).isAvailable();
            return ResponseEntity.ok(new HealthResponse(available, available ? "OK" : "Unavailable"));
            
        } catch (Exception e) {
            logger.error("Error checking client health for type: {}", clientType, e);
            return ResponseEntity.ok(new HealthResponse(false, "Error: " + e.getMessage()));
        }
    }
    
    // 请求和响应模型类
    
    public static class ChatRequest {
        private String clientType;
        private String model;
        private List<LlmMessage> messages;
        private Map<String, String> clientConfig;
        
        // Getters and Setters
        public String getClientType() {
            return clientType;
        }
        
        public void setClientType(String clientType) {
            this.clientType = clientType;
        }
        
        public String getModel() {
            return model;
        }
        
        public void setModel(String model) {
            this.model = model;
        }
        
        public List<LlmMessage> getMessages() {
            return messages;
        }
        
        public void setMessages(List<LlmMessage> messages) {
            this.messages = messages;
        }
        
        public Map<String, String> getClientConfig() {
            return clientConfig;
        }
        
        public void setClientConfig(Map<String, String> clientConfig) {
            this.clientConfig = clientConfig;
        }
    }
    
    public static class ClientTypesResponse {
        private String[] clientTypes;
        
        public ClientTypesResponse(String[] clientTypes) {
            this.clientTypes = clientTypes;
        }
        
        public String[] getClientTypes() {
            return clientTypes;
        }
        
        public void setClientTypes(String[] clientTypes) {
            this.clientTypes = clientTypes;
        }
    }
    
    public static class ModelsResponse {
        private String[] models;
        
        public ModelsResponse(String[] models) {
            this.models = models;
        }
        
        public String[] getModels() {
            return models;
        }
        
        public void setModels(String[] models) {
            this.models = models;
        }
    }
    
    public static class HealthResponse {
        private boolean available;
        private String status;
        
        public HealthResponse(boolean available, String status) {
            this.available = available;
            this.status = status;
        }
        
        public boolean isAvailable() {
            return available;
        }
        
        public void setAvailable(boolean available) {
            this.available = available;
        }
        
        public String getStatus() {
            return status;
        }
        
        public void setStatus(String status) {
            this.status = status;
        }
    }
}